﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;

namespace Baison.FastApp
{
    public class JsonRpcRequest
    {
        /// <summary>
        /// 请求语言，支持en,zh_cn等，默认zh_cn
        /// </summary>
        protected string _lang;
        public string Lang
        {
            get { return _lang; }
            set { _lang = value; }
        }

        /// <summary>
        /// jsonrpc的网站地址
        /// </summary>
        protected string _hostUrl;
        public string HostUrl
        {
            get { return _hostUrl; }
            set { _hostUrl = value; }
        }

        /// <summary>
        /// 必须，API应用的标志符.
        /// </summary>
        protected string _appKey;
        public string AppKey
        {
            get { return _appKey; }
            set { _appKey = value; }
        }

        /// <summary>
        /// 可选，默认为APP_SALT，用于函数参数鉴权，将相关参数通过md5,hmac加密为一个sign值
        /// </summary>
        protected string _appSecret;
        public string AppSecret
        {
            get { return _appSecret; }
            set { _appSecret = value; }
        }

        /// <summary>
        /// 请求方式 默认GET
        /// </summary>
        protected RequestType _requestType;
        public RequestType RequestType
        {
            get { return _requestType; }
            set { _requestType = value; }
        }

        /// <summary>
        /// 应用app访问taobao的通用参数设置，一般不改变默认值，包括：
        /// string app_sign_method :可选，签名方法，md5,hmac，默认是 'md5'。
        /// </summary>
        public IDictionary<string, string> AppSetting = new Dictionary<string, string>();

        /// <summary>
        /// 上次调用API接口的URL.
        /// </summary>
        protected string _url;
        protected string Url
        {
            get { return _url; }
            set { _url = value; }
        }

        #region Construct

        public JsonRpcRequest()
        {
            Lang = "zh_cn";
            RequestType = RequestType.HttpMethodGet;
        }

        public JsonRpcRequest(string hostUrl, string appKey, string appSecret)
        {
            Lang = "zh_cn";
            RequestType = RequestType.HttpMethodGet;

            HostUrl = hostUrl;
            AppKey = appKey;
            AppSecret = appSecret;
        }
        #endregion

        #region Public Methods

        /// <summary>
        /// 得到taobo API的返回值，JSON字符串。
        /// </summary>
        /// <param name="action">要调用的api接口的cmdid字符串，如orderinfo/product_list，如果为空，将返回null.</param>
        /// <param name="paramets">要调用的api接口的参数数组，一般通用的参数不要传，如charset，format等。</param>
        /// <returns></returns>
        public string Request(string action, IDictionary<string, string> paramets)
        {
            if (string.IsNullOrEmpty(action)) return null;
            if (string.IsNullOrEmpty(AppKey)) return null;

            foreach (var set in AppSetting)
            {
                paramets[set.Key] = set.Value;
            }
			paramets["app_sign"] = CreateSign(paramets);
            paramets["app_key"] = AppKey;
            paramets["app_act"] = action;
            paramets["app_mode"] = "func";
            paramets["app_lang"] = Lang;
            
            Url = HostUrl;

            string retJson = null;
            switch (RequestType)
            {
                case RequestType.HttpMethodPost:
                    retJson = Post(paramets);
                    break;
                case RequestType.HttpMethodGet:
                    retJson = Get(paramets);
                    break;
                case RequestType.HttpMethodPostWithFile:
                    retJson = PostFile(paramets);
                    break;
            }
            return retJson;
        }

        #endregion

        protected string Get(IDictionary<string, string> paramets)
        {
            string data = CreateStrParam(paramets); //GET方法传递的参数；
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(HostUrl + "?" + data);
            request.Method = "GET";
            request.ContentType = "application/json;charset=UTF-8";

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            using (StreamReader resStream = new StreamReader(response.GetResponseStream(), Encoding.Default))
            {
                return resStream.ReadToEnd();
            }
        }

        protected String Post(IDictionary<string, string> paramets)
        {
            byte[] data = CreateBytesParam(paramets);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(HostUrl);
            request.Method = "POST";
            request.ContentType = "application/json;charset=UTF-8";
            request.ContentLength = data.Length;

            using (Stream reqStream = request.GetRequestStream())
            {
                reqStream.Write(data, 0, data.Length);
            }

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            using (StreamReader resStream = new StreamReader(response.GetResponseStream(), Encoding.Default))
            {
                return resStream.ReadToEnd();
            }
        }

        protected String PostFile(IDictionary<string, string> paramets)
        {
	    //待更新
            return string.Empty;
        }

        #region Protected Methods

        /// <summary>
        /// GET参数
        /// </summary>
        /// <param name="paramets">参数</param>
        /// <returns></returns>
        protected string CreateStrParam(IDictionary<string, string> paramets)
        {
            StringBuilder paramok = new StringBuilder();

            foreach (KeyValuePair<string,string> item in paramets)
            {
                if (!string.IsNullOrEmpty(item.Key) && !string.IsNullOrEmpty(item.Value))
                {
                    paramok.Append(string.Format("{0}={1}&", item.Key, item.Value));                   
                }
            }
            string ret = paramok.ToString();
            return ret.Substring(0, ret.Length - 1);
        }

        /// <summary>
        /// POST参数
        /// </summary>
        /// <param name="paramets">参数</param>
        /// <returns></returns>
        protected byte[] CreateBytesParam(IDictionary<string, string> paramets)
        {
            string ret = CreateStrParam(paramets);
            return Encoding.Default.GetBytes(ret);
        }

        /// <summary>
        /// 生成签名
        /// </summary>
        /// <param name="paramets"></param>
        /// <returns></returns>
        protected string CreateSign(IDictionary<string, string> paramets)
        {
            StringBuilder sign = new StringBuilder();

            sign.Append(AppKey);

            //根据key排序
            Dictionary<string, string> sortParamets = new Dictionary<string, string>();
            List<string> keys = new List<string>(); //ICollection转换为List后排序
            foreach (string key in paramets.Keys)
            {
                keys.Add(key);
            }
            keys.Sort();
            foreach (string key in keys)
            {
                sortParamets[key] = paramets[key];
            }
            //拼接参数
            foreach (KeyValuePair<string, string> item in sortParamets)
            {
                if(!string.IsNullOrEmpty(item.Key) && !string.IsNullOrEmpty(item.Value))
                {
                    sign.Append(item.Key);
                    sign.Append(item.Value);
                }
            }
            //盐值
            byte[] appSecret = Encoding.Default.GetBytes(AppSecret);

            return SimpleHash.ComputeHash(sign.ToString(), "MD5", appSecret).ToUpper(); //MD5加密
        }

        #endregion
    }
}
